#include "VanishingPoint.h"
#include "Segment.h"
#include "Point2f.h"
#include "PolygonPath.h"
#include "KlausImage.h"
#include "ImageSegment.h"


#include "ofxThread.h"

#include "ofxOpenCv.h"
#include "cv.h"

#include "../libsugar/parser/ParseSvgToObject.h" 
#include "../libsugar/primitives/SugarObjects.h" 

#include <vector>
#include <algorithm>
#include <limits>
#include <fstream>


#define USE_TIFFS // comment me out if you are using those half-size pngs. If this is defined. It will look for .tiff files in original size;



#ifndef __ABLIEFERN_SEGMENT_ORACLE
#define __ABLIEFERN_SEGMENT_ORACLE



namespace abliefern {
	
	class SegmentOracle : public ofxThread {
		
	public:
		SegmentOracle(KlausImage* theKlausImage, std::string theInputPathName, std::string theSvgPathName, std::string theOutputPathName, std::string theOutPutSuffix);
		~SegmentOracle();
		
		
		void draw();
		void update();
		
		
		bool hasFinishedCompletely();
		
		/* Threading */
		void start();
		void kill();
		void threadedFunction();
		
		KlausImage* getKlausImage();
		
		std::vector<ImageSegment> getSegments();
		
		void addVanishingPoint(VanishingPoint theVP);
		
		
		
	private:
		bool _myIsFinishedCompletely;

		std::vector<ImageSegment> _mySegments;
		int _myLineCount;
		
		/* File location */
		KlausImage* _myKlausImage;
		std::string _myInputPathName;
		std::string _mySvgPathName;
		std::string _myOutputPathName;
		
		/* File naming */
		std::string _myOutputSuffix;
		

		
		/* Images */
		ofImage _myOriginalImage;
		ofxCvColorImage _myCvImage;
		
		
		/* Parameters */
		int _myLineThreshold;
		int _myBorderThreshold;
		
		int _myLineThresholdSquared;
		
		int _myMaxSegments;
		
		
		/* Count */
		float _myBorderLength;
		float _myPathLength;
		
		
		
		std::vector<abliefern::VanishingPoint> _myVPs;
		std::vector<abliefern::PolygonPath> _myPaths;
		
		void loadImage();

		
		/* Svg Parsing */
		void parseSvg(std::string theFileName);
		void parse(SugElement* element);
		void parsePath(SugPathElement* path);
		
		/* VP */
		void countLine(float theX1, float theY1, float theX2, float theY2);
		
		
		
		
		/* Saving */
		void saveSegment(std::string theBaseFilename, std::string theFileName);
		
		/* Bounds */
		void updateBounds(float theX, float theY);
		void resetBounds();
		void resetCounts();

		
		
		/* Shape Bounding box */
		float _myMinX;
		float _myMinY;
		float _myMaxX;
		float _myMaxY;
		
		
		/* Helper */ 
		static float bezierPoint(float a, float b, float c, float d, float t);
		bool fileExists(std::string theFileName);

	};
	
}

#endif